package com.leigq.www.producer.task;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.leigq.www.common.entity.Order;
import com.leigq.www.producer.constant.MessageLogConstant;
import com.leigq.www.producer.entity.BrokerMessageLog;
import com.leigq.www.producer.enumeration.MessageLogStatusEnum;
import com.leigq.www.producer.service.OrderSender;
import com.leigq.www.producer.service.BrokerMessageLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * RabbitMQ消息重投任务
 * <br/>
 * 用于处理加入到RabbitMQ中的订单队列
 * <p>
 * 创建人：asus <br>
 * 创建时间：2019-02-16 21:40 <br>
 * <p>
 * 修改人： <br>
 * 修改时间： <br>
 * 修改备注： <br>
 * </p>
 */
@Slf4j
@Component
public class OrderTask {

    @Autowired
	private ObjectMapper objectMapper;

    @Autowired
	private BrokerMessageLogService messageLogService;

    @Autowired
	private OrderSender orderSender;

	/**
	 * 重头规则：每隔一定时间去数据库查询 状态为确认中 并且 下次重试时间 <= 当前时间 进行重投
	 * <br/>
	 * create by: leigq
	 * <br/>
	 * create time: 2019/7/25 17:47
	 */
	@Scheduled(cron = "*/10 * * * * ?")
	public void rethrow() {
		log.info("重投RabbitMQ消息任务开始执行......");

		// 查询 状态为确认中 并且 下次重试时间 <= 当前时间 进行重投
		List<BrokerMessageLog> logs = messageLogService.findOvertimeMsg();

		// 循环重投
		logs.forEach(messageLog -> {
			// 尝试次数 >=3 次将状态改为失败，此时需要手动检查 MQ 的状态
			if (messageLog.getTryCount() >= MessageLogConstant.TRY_COUNT) {
				messageLog.setStatus(MessageLogStatusEnum.FAIL.getValue());
				messageLogService.update(messageLog);
			} else {
				// 开始重投
				try {
					/* 发送消息至RabbitMQ */
					orderSender.sendOrder(objectMapper.readValue(messageLog.getMessage(), Order.class));
				} catch (Exception e) {
					log.error("发送订单消息至RabbitMQ异常", e);
				}
				// 重投次数 + 1
				messageLog.setTryCount(messageLog.getTryCount() + 1);
				messageLogService.update(messageLog);
			}
		});

	}

}
